package ucsyslogic

import (
	"context"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"go.uber.org/zap"
	"navi-mumbai/app/rpc/model/pg/usercenter"
	"navi-mumbai/common/key/userkey"
	"navi-mumbai/common/utils"
	"navi-mumbai/common/xerr"
	"time"

	"navi-mumbai/app/rpc/usercenter/internal/svc"
	"navi-mumbai/app/rpc/usercenter/pb"

	"github.com/zeromicro/go-zero/core/logx"
)

type AddUserRewardLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewAddUserRewardLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddUserRewardLogic {
	return &AddUserRewardLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// 赠送礼物
func (l *AddUserRewardLogic) AddUserReward(in *pb.AddUserRewardReq) (*pb.AddUserRewardResp, error) {
	defer utils.RecoverPanic()

	// 检查礼物限制
	var curCnt int64
	var isAllow bool
	var err error
	switch in.ActivityId {
	case userkey.ActivityIdRegister: // 注册礼物不走这里
		return &pb.AddUserRewardResp{}, nil
	case userkey.ActivityIdLogin: // 登录礼物不走这里
		return &pb.AddUserRewardResp{}, nil
	case userkey.ActivityIdLuckyReward: //
		curCnt, isAllow, err = l.checkLuckyReward(in.Uid)
		if err != nil {
			l.Logger.Errorf("err == ", zap.Error(err))
			return nil, err
		}
		if !isAllow {
			l.Logger.Errorf("reward limit error !")
			return nil, xerr.NewGrpcErrCodeMsg(xerr.UserRewardLimitError, "reward limit")
		}

	default:
		l.Logger.Errorf("invalid reward type !")
		return nil, xerr.NewGrpcErrCodeMsg(xerr.RequestParamError, "invalid reward type")
	}

	err = l.svcCtx.UserAccountModel.Trans(l.ctx, func(ctx context.Context, tx sqlx.Session) error {
		// 更新限制
		now := time.Now()
		err2 := l.svcCtx.UserRewardLimitModel.UpdateLuckyReward(l.ctx, tx, in.Uid, curCnt, &now)
		if err2 != nil {
			l.Logger.Errorf("err == ", zap.Error(err2))
			return xerr.NewGrpcErrCodeMsg(xerr.DbError, err2.Error())
		}

		// 增加礼物
		unm := usercenter.UserReward{
			Uid:          in.Uid,
			RewardType:   in.RewardType,
			RewardAmount: in.RewardAmount,
			ActivityId:   in.ActivityId,
			State:        userkey.RewardStateCreated,
		}

		_, err2 = l.svcCtx.UserRewardModel.InsertTrans(ctx, tx, &unm)
		if err2 != nil {
			l.Logger.Errorf("err == ", zap.Error(err2))
			return xerr.NewGrpcErrCodeMsg(xerr.DbError, err2.Error())
		}

		// 更新礼物数
		err2 = l.svcCtx.UserRewardStatModel.Incr(ctx, tx, in.Uid, 1)
		if err2 != nil {
			l.Logger.Errorf("err == ", zap.Error(err2))
			return xerr.NewGrpcErrCodeMsg(xerr.DbError, err2.Error())
		}
		return nil
	})
	if err != nil {
		l.Logger.Errorf("err == ", zap.Error(err))
		return nil, err
	}

	return &pb.AddUserRewardResp{}, nil
}

func (l *AddUserRewardLogic) checkLuckyReward(uid int64) (curCnt int64, isAllow bool, err error) {
	var ulr *usercenter.UserRewardLimit
	// 检查是否已经领取过
	var cnt int64
	cnt, err = l.svcCtx.UserRewardModel.CountNotReceived(l.ctx, uid, userkey.ActivityIdLuckyReward)
	if err != nil {
		l.Logger.Errorf("err == ", zap.Error(err))
		err = xerr.NewGrpcErrCodeMsg(xerr.DbError, err.Error())
		return
	}
	if cnt > 0 {
		return
	}
	// 检查是否超过每日领取上限
	ulr, err = l.svcCtx.UserRewardLimitModel.FindOne(l.ctx, uid)
	if err != nil && err != usercenter.ErrNotFound {
		l.Logger.Errorf("err == ", zap.Error(err))
		err = xerr.NewGrpcErrCodeMsg(xerr.DbError, err.Error())
		return
	}
	if ulr == nil {
		ulr = &usercenter.UserRewardLimit{
			Uid: uid,
		}
		_, err = l.svcCtx.UserRewardLimitModel.Insert(l.ctx, ulr)
		if err != nil {
			l.Logger.Errorf("err == ", zap.Error(err))
			err = xerr.NewGrpcErrCodeMsg(xerr.DbError, err.Error())
			return
		}
		isAllow = true
		curCnt = 1
	} else {
		if ulr.TodayLuckyRewardCnt >= userkey.LuckyRewardLimit && ulr.LuckyRewardUpdateTime.Day() == time.Now().Day() {
			return
		}
		isAllow = true
		curCnt = ulr.TodayLuckyRewardCnt + 1
	}
	return
}
